require 'Map Generator/Map'

def createMap(x, y, numCountries, islandStyle, coastPercentKeep, avgCountrySize, countryProp, countryOddPercent, minLakeSize)

	# numCountries			number of countries desired
	# islandStyle			how many islands to have (none, some, lots)
	# coastPercentKeep		how much coastal area to preserve (0-100)
	# avgCountrySize		average size of a country
	# countryProp			how proportionate one country is to the next (0-100)
	# countryOddPercent		how oddly shapen a country is (0-100)
	map = Map.new(x, y)
	
	lakeNum = WATERBODY_START + 1

	country = 0
	
	#looping to generate a specific number of countries
	while country < numCountries and roomForCountry(map)
	
	
	
		puts "country " + country.to_s
	
		countryDone = false
		
		
		#working on a particular country
		while not countryDone and roomForCountry(map)
		

		
			#find a starting position for the country
			getStartDone = false
			while not getStartDone
			
				startX = rand(map.width)
				startY = rand(map.height)
				
				if islandStyle == ISLAND_STYLE_NONE and map.cell(startX, startY) == TILE_COASTLINE
					getStartDone = true
				elsif islandStyle == ISLAND_STYLE_LOTS and (map.cell(startX, startY) == TILE_COASTLINE or map.cell(startX, startY) == TILE_WATER)
					getStartDone = true
				elsif map.cell(startX, startY) == TILE_COASTLINE and coastPercentKeep >= rand(101) or map.cell(startX, startY) == TILE_WATER and coastPercentKeep <= rand(101)
					getStartDone = true
				end
			
			end #get Start
			
			#tentative country block
			tent = []
			tent[0] = [startX, startY]
			tentNum = 1
			
			#get the size in cells of the country
			countrySize = getCountrySize(avgCountrySize, countryProp)
			puts "country size " + countrySize.to_s
			newOrder = true
			validCountry = true

			#count the number of cells we've tried so far
			cellTry = 0
			
			while (tentNum < countrySize) and (not countryDone)
			
				#scramble the elements to ensure randomness
				if newOrder == true
					tent = jumbleArray(tent, false)
					newOrder = false
					
					#set the first cell to try
					if rand(100) < countryOddPercent
						useCell = tent.length - 1
					else
						useCell = 0
					end
				end
				

				
				x = tent[useCell][0]
				y = tent[useCell][1]
				
				#directions with padding for jumbleArray
				directions = [1, 2, 3, 4, 5]
				directions = jumbleArray(directions, true)
				#delete the last element to remove padding
				directions = directions.delete_at(4)
				
				directionTry = rand(4)
				directionTryCount = 0
				done = false
				while directionTryCount < 4 and (not done)
									
					case directionTry
					
						when 0 #UP
						
							oneAway = y-1
							if oneAway >= 0
								#if this cell is clear for use
								if clearDirection(x, oneAway, map.cell(x, oneAway), tent)
								
									y = oneAway
									
									tentNum += 1
									tent << [x, y]
									done = true
									
									countryDone = true if tentNum >= countrySize
								else
									#blocked - get new direction
									directionTry += 1
									directionTry = 0 if directionTry == 4
									directionTryCount += 1
								end
							else
								#off the top - get new direction
								directionTry += 1
								directionTry = 0 if directionTry == 4
								directionTryCount += 1
							end
						
						when 1 #DOWN
						
							oneAway = y+1
							if oneAway <= map.height - 1
								#if this cell is clear for use
								if clearDirection(x, oneAway, map.cell(x, oneAway), tent)
									y = oneAway
									
									tentNum += 1
									tent << [x, y]
									done = true
									
									countryDone = true if tentNum == countrySize
								else
									#blocked - get new direction
									directionTry += 1
									directionTry = 0 if directionTry == 4
									directionTryCount += 1
								end
							else
								#off the top - get new direction
								directionTry += 1
								directionTry = 0 if directionTry == 4
								directionTryCount += 1
							end
						
						when 2 #LEFT

							oneAway = x-1
							if oneAway >= 0
								#if this cell is clear for use
								if clearDirection(oneAway, y, map.cell(oneAway, y), tent)
									x = oneAway
									
									tentNum += 1
									tent << [x, y]
									done = true
									
									countryDone = true if tentNum == countrySize
								else
									#blocked - get new direction
									directionTry += 1
									directionTry = 0 if directionTry == 4
									directionTryCount += 1
								end
							else
								#off the top - get new direction
								directionTry += 1
								directionTry = 0 if directionTry == 4
								directionTryCount += 1
							end
						
						when 3 #RIGHT
						
							oneAway = x+1
							if oneAway <= map.width - 1
								#if this cell is clear for use
								if clearDirection(oneAway, y, map.cell(oneAway, y), tent)
									x = oneAway
									
									tentNum += 1
									tent << [x, y]
									done = true
									
									countryDone = true if tentNum == countrySize
								else
									#blocked - get new direction
									directionTry += 1
									directionTry = 0 if directionTry == 4
									directionTryCount += 1
								end
							else
								#off the top - get new direction
								directionTry += 1
								directionTry = 0 if directionTry == 4
								directionTryCount += 1
							end
					
					end #case directionTry
					
				
				end #while directionTry < 4 and not done
									
				if directionTryCount == 4
					#this block is boxed in, move to the next one in the list
					
					newOdrer = false
					
					useCell += 1
					useCell = 0 if useCell > tentNum - 1
					
					cellTry += 1
					
					#if we've tried every cell, unusable starting location
					if cellTry > tentNum - 1
						puts "executed"
						
					
						#set every cell in this area to unusable
						for n in (0..(tent.length) -1)
							map.setCell(tent[n][0], tent[n][1], lakeNum)
						end
						
						lakeNum += 1
						
						countryDone = true
						validCountry = false
					end
				else
					cellTry = 0
					#re-jumble the cells in the country
					#so that a new one is chosen to try from
					newOrder = true
				end
			
			end #tentNum < countrySize
		
			#if the validCountry flag wasnt set to false at some point
			if validCountry == true
			
				#write country to map
				for n in (0..(tent.length) -1)
					map.setCell(tent[n][0], tent[n][1], country+1)
				end
				
				country += 1
				outlineCoastline(country+1, map)
			
			end
		
		end #countryDone
	
	end
	
	lakeNum = fillSpacesWithOceans(map, lakeNum)
	lakeNum = removeSmallWater(minLakeSize, map, lakeNum)
	#map = replaceWaterWithOcean(map, lakeNum)
	
	#map = outlineCoastline(0, map)

	puts map.to_s + "."
	
	return map, country, lakeNum-WATERBODY_START

end




#determines if there is room for another country
#given map
#returns true if there is water on it
#false otherwise
def roomForCountry(map)

	for x in (0..map.width-1)
	
		for y in (0..map.height-1)
			
			if map.cell(x, y) == TILE_WATER or map.cell(x, y) == TILE_COASTLINE
				return true
			end
		
		end
	
	end
	
	return false

end

def getCountrySize(countrySize, countryProportionality)
	
	if rand(2) == 0
		#size = countrySize - (rand(100).to_f/100) * countrySize * (countryProportionality.to_f/100)
		size = countrySize - countrySize*(100-countryProportionality)/100*rand(100)/100
	else
		size = countrySize + countrySize*(100-countryProportionality)/100*rand(100)/100
		#size = countrySize - (rand(100).to_f/100) * countrySize * (countryProportionality.to_f/100)
	end
	
	return size.to_i

end

#jumble the array, dont touch the last element
def jumbleArray(array, all = false)

	return array if array.length <= 3


	if all

		for	n in (0..(array.length) -2)
		
			newInd = rand((array.length) - 2)
			while newInd == n
				newInd = rand((array.length) - 2)
			end
			
			temp = array[n]
			array[n] = array[newInd]
			array[newInd] = temp
		
		end

	else
	
		newInd = rand((array.length) - 2)
		temp = array[0]
		array[0] = array[newInd]
		array[newInd] = temp
		
	end

	return array

end

def clearDirection(x, y, mapPoint, tent)

	clearDir = true
	
	if mapPoint != TILE_WATER and mapPoint != TILE_COASTLINE
		clearDir = false
	end


	tent.each {|point|
	
		clearDir = false if point[0] == x and point[1] == y
	
	}
	
	return clearDir

end


def outlineCoastline(country, map)

	for x in (0..map.width - 1)
	
		for y in (0..map.height - 1)
		
			if country == 1 and map.cell(x, y) == TILE_COASTLINE or map.cell(x, y) == TILE_UNUSABLE
			
				map.setCell(x, y, TILE_WATER)
			
			end
			
			#cell is water
			if map.cell(x, y) == TILE_COASTLINE or map.cell(x, y) == TILE_WATER or map.cell(x, y) > WATERBODY_START
			
				foundLand = false
				
				if y-1 >= 0
					foundLand = true if map.cell(x, y-1) > LANDBODY_START and map.cell(x, y-1) < WATERBODY_START
				end
				
				if y+1 <= map.height - 1
					foundLand = true if map.cell(x, y+1) > LANDBODY_START and map.cell(x, y+1) < WATERBODY_START
				end
				
				if x-1 >= 0
					foundLand = true if map.cell(x-1, y) > LANDBODY_START and map.cell(x-1, y) < WATERBODY_START
				end
				
				if x+1 <= map.width - 1
					foundLand = true if map.cell(x+1, y) > LANDBODY_START and map.cell(x+1, y) < WATERBODY_START
				end
				
				if foundLand == true
					
					map.setCell(x, y, TILE_COASTLINE)
					
				else
				
					map.setCell(x, y, TILE_WATER)
				
				end
			
			end #cell is water
		
		end
	
	end
	
	#return map

end

def removeSmallWater(minSize, map, numLakes)
	
	n = WATERBODY_START + 1

	while n < numLakes
	
		size = tallyElementInMap(n, map)
		
		puts n, size, minSize, ""
		
		if size < minSize
		
			replaceAndShiftDown(n, map)
			numLakes -= 1
		else
			n += 1
		end
	
	end
	
	return numLakes

end

def replaceAndShiftDown(element, map)
	
	
	for x in (0..map.width-1)
		for y in (0..map.height-1)

			value = map.cell(x, y)

			if value == element
				replacement = getLandReplacement(x, y, map)
				map.setCell(x, y, replacement)
				
			elsif value > element
				map.setCell(x, y, value - 1)
			end
		
		end
	end


end

def getLandReplacement(x, y, map)

	step = rand(4)
	
	value = TILE_INVALID
	
	while value == TILE_INVALID
		
		case step
		
			when 0
				value = map.cell(x, y-1) if y > 0 
			
			when 1
				value = map.cell(x, y+1) if y < map.height
			
			when 2
				value = map.cell(x-1, y) if x > 0
			
			when 3
				value = map.cell(x+1, y) if x < map.width

		end
		
		if value > LANDBODY_START and value < WATERBODY_START
			#working value
		else
			step += 1
			step = 0 if step == 9
			value = TILE_INVALID
		end
		
	end
	
	return value

end

def tallyElementInMap(value, map)
	
	count = 0
	
	for x in (0..map.width-1)
		for y in (0..map.height-1)
		
			count += 1 if map.cell(x, y) == value
	
		end
	end
	
	return count

end

def fillSpacesWithOceans(map, numLakes)

	for x in 0..map.width-1
		for y in 0..map.height-1
	
			if map.cell(x, y) == TILE_WATER or map.cell(x, y) == TILE_COASTLINE
			
				fillRegion(x, y, map, numLakes)
				numLakes += 1
				puts numLakes.to_s
			
			end
	
		end
	end
	
	return numLakes

end

def fillRegion(x, y, map, numLakes)
	

	return if x < 0 or x > map.width - 1
	return if y < 0 or y > map.height - 1
	map.setCell(x, y, numLakes)
	
	
	if map.cell(x+1, y) == TILE_WATER or map.cell(x+1, y) == TILE_COASTLINE
		
		fillRegion(x+1, y, map, numLakes)
		
	end

	if map.cell(x-1, y) == TILE_WATER or map.cell(x-1, y) == TILE_COASTLINE
		
		fillRegion(x-1, y, map, numLakes)
		
	end
	
	if map.cell(x, y+1) == TILE_WATER or map.cell(x, y+1) == TILE_COASTLINE

		fillRegion(x, y+1, map, numLakes)
		
	end
	
	if map.cell(x, y-1) == TILE_WATER or map.cell(x, y-1) == TILE_COASTLINE

		fillRegion(x, y-1, map, numLakes)
		
	end
		

end


def createNames(number, water)

	names = []

	number.times do
		names << createName(water)
	end
	
	return names

end

def createName(useWater)

	starts = ["a", "e", "i", "o", "u"]
	vowels = ["a", "e", "i", "o", "u", "ia"]
	middle = ["b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n", "p", "r", "s", "t", "v", "w", "ch", "sh", "cl", "bl", "vr"]
	consonants = ["b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n", "p", "r", "s", "t", "v", "w", "ch", "sh"]
	
	water = ["Bay", "Sea", "Ocean", "Lake"]
	
	name = ""
	
	if rand(2) == 1
	
		name << starts[rand(5)]
	
	end
	
	count = 0
	
	puts "starting"
	
	while (rand(7-count) < 4 or count < 1) and count < 2
		
		count+= 1
		
		name << middle[rand(middle.length)]
		
		name << vowels[rand(vowels.length)]

	end
	
	if rand(2) == 1
		name << consonants[rand(consonants.length)]
	end
	
	name.capitalize!
	
	if useWater == true
	
		name << " "
		name << water[rand(water.length)]
	
	end
	
	puts name
	
	return name
end

def createTroopCounts(number, middle, maxVariance)

	values = []

	number.times do
		values << createTroopCount(middle, maxVariance)
	end
	
	return values

end

def createTroopCount(middle, maxVariance)

	variance = maxVariance * rand(100) / 100
	
	if rand(2) == 0
		return middle - variance
	else
		return middle + variance
	end

end
